/**
 * Copyright (c) 2015, 小智科技（版权声明）
 *
 * @file	CustomServerApplication.cpp
 * @brief CustomServerApplication 类的实现。包括程序的初始化，反初始化部分。
 *
 *
 * @author: 		yuhaiyang
 * @date: 		2015年5月6日
 *
 * 修订说明:初始版本
 */
#include "CustomServerApplication.h"
#include <Poco/AutoPtr.h>
#include <Poco/FileChannel.h>
#include <Poco/Logger.h>
#include <Poco/PatternFormatter.h>
#include <Poco/FormattingChannel.h>
#include <Poco/Exception.h>
#include "Poco/Foundation.h"
#include <stdint.h>
#include <sstream>
#include <pthread.h>
#include "Poco/Net/TCPServer.h"
#include <Poco/JSON/JSONException.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "SendMq/SendMq.h"

#include "Service/CapPackService.h"


using namespace Poco;
using Poco::Logger;

#define MODE "CustomServerApplication:"



CustomServerApplication::CustomServerApplication( )
{
	_helpRequested = false;
}


CustomServerApplication::~CustomServerApplication( )
{
}

/**
 *@brief 程序的初始化部分,继承于 Application 类
 */
void CustomServerApplication::initialize( Application& self )
{
	if ( _helpRequested )
	{
		return;
	}
	try
	{
		ServerApplication::initialize( self );
		try
		{
            Util::Application::loadConfiguration( DEFAULT_CONG_PATH, PRIO_APPLICATION );

            SendMq::Instance().Amqp_Init_Mq(CONF.getString("rabbitmqIp").c_str(),
                                            CONF.getInt("rabbitmqPort"),
                                            CONF.getString("rabbitmqUser").c_str(),
                                            CONF.getString("rabbitmqPasswd").c_str(),
                                            CONF.getString("MessagePush_QueueName").c_str(),
                                            CONF.getString("MessagePush_RoutKey").c_str(),
                                            CONF.getString("MessagePush_Status").c_str());
            // load  configuration files, if present
        }
        catch( Poco::JSON::JSONException& e )
        {
            LOG.fatal("conf file: Invalid format %s" , e.displayText() );
        }
        catch( Poco::FileNotFoundException &e )
		{
            LOG.fatal("conf file: %s" , e.displayText() );
            std::cerr << "Confguer file error: " << e.displayText( ) << std::endl;
		}

		// 初始化日志
		initLog( );
        LOG.information("init ok!");
	}
	catch( Poco::FileNotFoundException &e )
	{
		std::cerr << "Log file error: " << e.displayText() << std::endl;
	}
}

/**
 *@bfier 程序的反初始化部分,继承于 Application 类
 */
void CustomServerApplication::uninitialize( void )
{
	if ( _helpRequested )
	{
		return ;
	}

	ServerApplication::uninitialize();
    logger().warning("uinit ok!!!");
}

/**
 *@brief 添加启动参数,继承于 Application 类。
 */
void CustomServerApplication::defineOptions( Util::OptionSet& options )
{
	ServerApplication::defineOptions( options );
		options.addOption(
				Util::Option("help", "h", "display help information on command line arguments").required(false).repeatable(false).callback(
                        Util::OptionCallback<CustomServerApplication>(this, &CustomServerApplication::handleHelp)) );
		options.addOption(
					Util::Option("version", "v", "display CollectFat version").required(false).repeatable(false).callback(
                                Util::OptionCallback<CustomServerApplication>(this, &CustomServerApplication::version)) );
}

/**
 *@brief 业务的的启动函数, 继承于 Application 类。
 */
int CustomServerApplication::main( const ArgVec& )
{
    try
    {
        if ( _helpRequested )
        {
            return Application::EXIT_OK;
        }


        CapPackService service;
        service.start();

        //等待结束信号
        LOG.information("Server start ok"  );

        waitForTerminationRequest();

        LOG.information("Server exit ok"  );
    }

    catch( Poco::Exception& e )
    {
        LOG.fatal("Server exit because of %s" ,e.displayText()  );
        return Application::EXIT_SOFTWARE;
    }

    return Application::EXIT_OK;
}

/**
 *@brief --help -h 的响应函数
 *
 *@param 模板要求,无实际意义。
 */
void CustomServerApplication::handleHelp( const std::string& , const std::string&  )
{
	_helpRequested = true;
	Util::HelpFormatter helpFormatter(options());
	helpFormatter.setCommand(commandName());
    helpFormatter.setUsage("");
    helpFormatter.setHeader("================帮助指令===================");
	helpFormatter.format(std::cout);
	stopOptionsProcessing( );
}

/**
 *@brief --version -v 的响应函数,打印程序版本。
 *
 *@param 模板要求,无实际意义。
 */
void CustomServerApplication::version(  const std::string& , const std::string& )
{
	_helpRequested = true;
    std::cout << 	"\n 抓包工具: CollectFat Ver 1.0\n"
				" 此程序用于收集胖 ap 信息\n\n" << std::endl;
	stopOptionsProcessing( );
}

/**
 *@brief  初始化程序的日志部分
 */
void CustomServerApplication::initLog( void )
{
	using Poco::FileChannel;

	//日志部分。
	Poco::AutoPtr<Poco::Channel> channel;
	{
		Poco::AutoPtr<FileChannel>fileChannel(new FileChannel);
        //指定日志路径
        std::string logdir = config().getString( "LOG.path" , DEFAULT_LOG_PATH );
        //检查当前目录下是否有log目录，否则创建一个
        if ( access(  logdir.c_str(), F_OK) != 0 )
        {
            //如果不存在就用mkdir函数来创建
            if ( mkdir( logdir.c_str(), 0777) )
            {
                std::cerr << strerror( errno ) << std::endl;
            }
        }
        //指定日志文件
        std::string logpath = config().getString( "LOG.file" , DEFAULT_LOG_FILE );

        fileChannel->setProperty( FileChannel::PROP_PATH, logdir+"/"+logpath );
		//设置 rotation 策略。
		std::string time = CONF.getString("LOG.ROTATION", DEFAULT_LOG_ROTATION );
		fileChannel->setProperty(FileChannel::PROP_ROTATION, time );
		//日志备份的后缀名加时间戳。
		fileChannel->setProperty(FileChannel::PROP_ARCHIVE, "timestamp");
		//日志备份之后会有时间后缀，默认是 utc 时间(国际标准时间), local (本地化，当地时间)
		fileChannel->setProperty(FileChannel::PROP_TIMES, "local");
		//把 备份的日志文件，进行压缩保存。
		fileChannel->setProperty(FileChannel::PROP_COMPRESS, "true");
		//删除过期的日志文件,格式为 "基数 单位" 支持的单位为 minutes, hours,days,weeks,months,
		//基数是可选的。默认为1
		time = CONF.getString( "LOG.PURGE_Age",DEFAULT_LOG_PURGEAGE );
		fileChannel->setProperty(FileChannel::PROP_PURGEAGE, time );

		//每条日志的格式。
		Poco::AutoPtr<Poco::PatternFormatter> patternFormatter(new Poco::PatternFormatter());
		patternFormatter->setProperty( "pattern", "%L%Y-%m-%d %H:%M:%S:%i %s(%p): %t" );

		//初始化　Channel
		channel = new Poco::FormattingChannel( patternFormatter, fileChannel );
	}
	//日志名字设置为　CollectFat。 2015-03-05 23:00:03:300 CollectFat(Information): shutting down
    setLogger( Logger::get("Packetcapture") );

    std::string level = CONF.getString( "LOG.level", DEFAULT_LOG_LEVEL );
	logger().setLevel( level );
	logger().setChannel(channel);	//把Application 的 log Channel 设置为我们指定的输出
    return;
}


